package com.winit.resource.manager;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.winit.common.base.beans.LoginUser;
import com.winit.common.util.Constants;
import com.winit.core.ci.vcs.SVN;
import com.winit.core.ci.vcs.exception.VCSException;
import com.winit.core.configuration.ConfigRepository;
import com.winit.core.configuration.ConfigRepositoryEditor;
import com.winit.core.configuration.util.ConfigRepositoryUtil;
import com.winit.core.host.power.RolePower;
import com.winit.core.host.power.beans.PowerParam;
import com.winit.core.host.power.beans.PowerType;
import com.winit.project.core.bean.ProjectInfo;
import com.winit.project.core.code.ProjectCodeConfig;
import com.winit.project.service.ProjectService;
import com.winit.project.util.ProjectUtil;
import com.winit.resource.beans.Config;
import com.winit.common.base.beans.RoleInfo;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * Created by wangjian on 16/7/22.
 */
@Component
public class ConfigFileManager {

    private static final Logger logger = LoggerFactory.getLogger(ConfigFileManager.class);

    @Autowired
    private ProjectService projectService;
    @Autowired
    private RolePower rolePower;

    public boolean isHasEnvPower(String userRole, String envName) {
        PowerParam powerParam = new PowerParam();
        powerParam.setName(envName);
        powerParam.setPowerType(PowerType.ENV);
        powerParam.setUserRole(userRole);
        return rolePower.getPower(powerParam);
    }

    public List<String> getProjectConfigFileNameList(ProjectCodeConfig projectCodeConfig,boolean isFilterConfig){
        List<String> list = new ArrayList<>();
        if(isFilterConfig){
            //获取默认配置文件,过滤掉不存在文件
            List<String> l = Constants.DEFAULT_DATA.get("configFile");
            for(String s:l){
                if(projectCodeConfig.isConfigFileExist(s)){
                    list.add(s);
                }
            }
            return list;
        }

        list = projectCodeConfig.getConfigFileList();
        return list;
    }

    public List<String> getEnvList(ConfigRepository configRepository) {
        List<String> temp = configRepository.getConfigEnvList();
        return temp;
    }

    public Map<String, Object> updateFile(String selectProject, String selectFile, String selectEnv) throws Exception {
        Map<String, Object> map = new HashMap<>();
        ProjectInfo projectInfo = projectService.getProjectInfo(selectProject);

        String projectConfigPath = ProjectUtil.getProjectConfigPath(projectInfo, selectFile);
        logger.info("更新工程配置文件,path=" + projectConfigPath);
        SVN projectSvn = new SVN(projectConfigPath);

        String configProjectName = StringUtils.isEmpty(projectInfo.getConfigProjectName()) ? selectProject : projectInfo.getConfigProjectName();

        String subModule = projectInfo.getSubModule();
        String configPath = null;
        if(StringUtils.isEmpty(subModule)){
            configPath = projectConfigPath.replace(ProjectUtil.getProjectCodePath(selectProject)
                    , ConfigRepositoryUtil.getDefaultConfigEnvPath(selectEnv) + "/" + configProjectName + "/");
        }else {
            configPath = projectConfigPath.replace(ProjectUtil.getProjectCodePath(selectProject)+subModule
                    , ConfigRepositoryUtil.getDefaultConfigEnvPath(selectEnv) + "/" + configProjectName);
        }
        logger.info("更新svnResource工程配置文件,path=" + configPath);
        SVN configSvn = new SVN(configPath);

        try {
            projectSvn.doUpdate();
            configSvn.doUpdate();
            map.put("code", "0");
        } catch (VCSException e) {
            map.put("code", "1");
            map.put("desc", e.getMessage());
        }
        return map;
    }

    public JSONArray getConfigFiles(Config config) throws Exception {

        String projectName = config.getSelectProject();
        String selectFile = config.getSelectFile().replace("$", "/");
        String selectEnv = config.getSelectEnv();

        JSONArray data = new JSONArray();
        ProjectInfo projectInfo = projectService.getProjectInfo(projectName);
        String filePath = projectInfo.getConfigPath() + "/" + selectFile;
        //1.获取工程代码中配置文件内容
        String codePath = ProjectUtil.getProjectCodePath(projectName);

        SVN svn = new SVN(projectInfo.getVcsPath(), codePath);

        ProjectCodeConfig projectCodeConfig = new ProjectCodeConfig(projectName, codePath, svn, projectInfo.getConfigPath());

        JSONObject jsonObject = new JSONObject();
        boolean exist = projectCodeConfig.isConfigFileExist(selectFile);
        jsonObject.put("exist", exist ? "0" : "1");
        jsonObject.put("path", "local:" + filePath);
        if (exist) {
            jsonObject.put("text", projectCodeConfig.getFileContent(selectFile));
        }
        data.add(jsonObject);

        //2.获取svnResource中配置文件内容
        JSONObject object = new JSONObject();

        String configProjectName = StringUtils.isEmpty(projectInfo.getConfigProjectName()) ? projectName : projectInfo.getConfigProjectName();

        boolean ex = Constants.CONFIG_REPOSITORY.isConfigFileExists(configProjectName, selectEnv, filePath);
        object.put("exist", ex ? "0" : "1");
        object.put("showPath", selectEnv + ":" + filePath);
        object.put("path", filePath);
        object.put("envName", selectEnv);
        if (ex) {
            object.put("text", Constants.CONFIG_REPOSITORY.getFileContent(configProjectName, selectEnv, filePath));
        }
        data.add(object);
        return data;
    }

    public boolean saveConfigFile(String selectProject, JSONObject rightObject) throws Exception {

        ProjectInfo projectInfo = projectService.getProjectInfo(selectProject);

        String configProjectName = StringUtils.isEmpty(projectInfo.getConfigProjectName()) ? selectProject : projectInfo.getConfigProjectName();

        String path = Constants.CONFIG_REPOSITORY.getConfigURI(configProjectName, rightObject.getString("envName"), rightObject.getString("path"));

        File file = new File(path);
        String dir = "";
        if (!file.getParentFile().exists()) {
            File f = getExistsParentFile(file);
            file.getParentFile().mkdirs();
            /**
             * 新建目录,一层一层添加到仓库
             */
            addDirToSvn(f);
            dir = f.getPath();
        }
        ConfigRepositoryEditor configRepositoryEditor = new ConfigRepositoryEditor(Constants.CONFIG_REPOSITORY_PATH, configProjectName, rightObject.getString("envName"), rightObject.getString("path"));

        if (!configRepositoryEditor.saveFile(rightObject.getString("text"))) {
            return false;
        }

        /**
         * 1.没有新建目录,提交指定文件
         * 2.有新建目录,先将文件add到仓库,然后提交目录
         */
        if (StringUtils.isEmpty(dir)) {
            SVN svn = new SVN(path);
            return configRepositoryEditor.commitCode(svn);
        } else {
            SVN svn = new SVN(path);
            svn.doAdd();
            SVN s = new SVN(dir);
            return configRepositoryEditor.commitCode(s);
        }
    }

    private File getExistsParentFile(File file) {
        if (file.getParentFile().exists()) {
            return file;
        } else {
            return getExistsParentFile(file.getParentFile());
        }
    }

    private void addDirToSvn(File file) throws VCSException {
        SVN svn = new SVN(file.getPath());
        svn.doAdd();

        if (file.isDirectory()) {
            for (File f : file.listFiles()) {
                if (f.isDirectory() && f.getName().equals(".svn")) {
                    continue;
                }
                addDirToSvn(f);
            }
        }
    }

    public boolean hasReadFilePower(LoginUser loginUser, String selectEnv, String selectFile) {

        if (StringUtils.startsWithIgnoreCase(selectEnv, "ops")
                && !loginUser.userHasRole("ops")
                && "password.properties".equalsIgnoreCase(selectFile)) {
            return false;
        }
        return true;
    }
}
